﻿#include "editor/windowman.h"

#include "editor/resource.h"

#include "editor/resview.h"
#include "editor/imview.h"
#include "editor/inspector.h"
#include "editor/whiteboard.h"
#include "editor/curvedit.h"
#include "editor/drawing/area.h"
#include "editor/drawing/toolbox.h"

#include "ui/controls.h"
#include "ui/native_dialogs.h"
#include <fstream>
#include "font.h"
#include "context.h"

using namespace std;
using namespace anip;

template<class T>
const void _windowMenu(editor::WindowManager* _this, ui::Menu& m, const wstring& name)
{
	ui::MenuHelper::button(m, name, 
		[&, _this](ui::MenuTextItem& self)
		{
			self.menu().markDelete();
			T* obj = new T(_this);
			obj->setPosition({ 50, 50 });
		});
}

void _GUITree(ui::Control* from, const string& prefix = ""s)
{
	cout << "- " << typeid(*from).name() 
		<< " [" << from->size().x << "x" << from->size().y << "]"
		<< " @ (" << from->position().x << ", " << from->position().y << ")";
	if (!from->getText().empty())
		wcout << L" [" << from->getText() << L"]";
	cout << endl;
	ANIP_ui_LoopOverChildrenFrom(((ui::Container*)from)->firstChild(), child)
	{
		if (child->next() == nullptr)
		{
			cout << prefix << "  \\";
			_GUITree(child, prefix + "   ");
		}
		else
		{
			cout << prefix << "  |";
			_GUITree(child, prefix + "  |");
		}
	}
}

void editor::WindowManager::processKey(Key k, ButtonAction action)
{
	if (k == Key::G && action == ButtonAction::Down && Context::holdingControl())
	{
		system("cls");
		_GUITree(topContainer());
	}
	EditorWindow::processKey(k, action);
}

editor::WindowManager::WindowManager() :
	EditorWindow(nullptr, Context::size())
{
	markTopLevel();
	setSize(Context::size());
	setPosition({ 100, 100 });

	auto menu = new ui::MenuBar(this);

	// ANIP_TODO: Clean up. This is completely chaotic. Need better ways
	// to create menus?
	ui::MenuHelper::barDropdown(*menu, r::menuProject,
		[&](ui::MenuBar::Item& self)
		{
			auto menu = new ui::Menu(this);
			ui::MenuHelper::button(*menu, r::menuNew);

			ui::MenuHelper::button(*menu, r::menuOpen,
				[&](ui::MenuTextItem& self)
				{
					self.menu().markDelete();
					if (!fileSaved)
						ui::NonIntrusiveDialog(r::msgProjectNotSaved)
						.addButton(r::msgCancel,
							[&]() { self.menu().markDelete(); })
						.addButton(r::msgProceed,
							[&]()
							{
								wstring file = ui::native::openFileDialog(
									L"\\", archivePath,
									{ {L"All files"s, L"*.*"s},
									  {L"ANIP Archive"s, L"*.aarch"s} }, 1);
								if (file.empty()) return;
								if (loadArchive(file))
									archivePath = file;
							})
						.show(*this);
				});

			ui::MenuHelper::separator(*menu);

			ui::MenuHelper::button(*menu, r::menuSave,
				[&](ui::MenuTextItem& self)
				{
					self.menu().markDelete();
					saveArchive(archivePath);
				}
			).enabled = !archivePath.empty();

			ui::MenuHelper::button(*menu, r::menuSaveAs,
				[&](ui::MenuTextItem& self)
				{
					self.menu().markDelete();
					wstring file = ui::native::saveFileDialog(
						L"\\", archivePath,
						{ {L"All files"s, L"*.*"s},
						  {L"ANIP Archive"s, L"*.aarch"s} },
						1, L"aarch");
					if (file.empty()) return;
					archivePath = file;
					saveArchive(archivePath);
				}
			);

			ui::MenuHelper::button(*menu, r::menuSaveAsNewVersion,
				[&](ui::MenuTextItem& self)
				{
				}
			).enabled = !archivePath.empty();

			ui::MenuHelper::separator(*menu);

			ui::MenuHelper::button(*menu, r::menuImportExistingProject);
			ui::MenuHelper::button(*menu, r::menuCompare);
			ui::MenuHelper::separator(*menu);
			ui::MenuHelper::button(*menu, r::menuPreferences);
			ui::MenuHelper::separator(*menu);
			ui::MenuHelper::button(*menu, r::menuExit,
				[&](ui::MenuTextItem& self)
				{
					if (!fileSaved)
						ui::NonIntrusiveDialog(r::msgProjectNotSaved)
						.addButton(r::msgCancel,
							[&]() { self.menu().markDelete(); })
						.addButton(r::msgProceed,
							[]() { Context::markWindowShouldClose(); })
						.show(*this);
					else
						Context::markWindowShouldClose();
				}).hoverColor = Colors::paleVioletRed;
			return menu;
		});

	ui::MenuHelper::barDropdown(*menu, L"视图",
		[&](ui::MenuBar::Item& self)
		{
			auto menu = new ui::Menu(this);
			ui::MenuHelper::groupHeader(*menu, L"窗口");
			_windowMenu<editor::ResourceView>(this, *menu, L"资源管理器");
			ui::MenuHelper::checkable(*menu, L"调色板");
			ui::MenuHelper::checkable(*menu, L"绘图区");
			ui::MenuHelper::checkable(*menu, L"时间线");
			_windowMenu<editor::Inspector>(this, *menu, L"细节设定");
			ui::MenuHelper::checkable(*menu, L"播放控制");
			ui::MenuHelper::checkable(*menu, L"图层结构");
			ui::MenuHelper::checkable(*menu, L"节点编程");
			ui::MenuHelper::separator(*menu);
			ui::MenuHelper::subMenu(*menu, L"工具",
				[&](auto&)
				{
					auto menu = new ui::Menu(this);
					_windowMenu<editor::Whiteboard>(this, *menu, L"白板");
					ui::MenuHelper::checkable(*menu, L"计算器");
					ui::MenuHelper::checkable(*menu, L"日影计算");
					return menu;
				});
			ui::MenuHelper::separator(*menu);
			ui::MenuHelper::button(*menu, L"召回画面外的窗口");
			return menu;
		});

	ui::MenuHelper::barDropdown(*menu, L"编辑",
		[&](ui::MenuBar::Item& self)
		{
			auto menu = new ui::Menu(this);
			ui::MenuHelper::button(*menu, L"撤销");
			ui::MenuHelper::button(*menu, L"重做");
			ui::MenuHelper::separator(*menu);
			ui::MenuHelper::button(*menu, L"复制");
			ui::MenuHelper::button(*menu, L"粘贴");
			return menu;
		});

	ui::MenuHelper::barDropdown(*menu, L"Debug",
		[&](ui::MenuBar::Item& self)
		{
			auto menu = new ui::Menu(this);
			ui::MenuHelper::button(*menu, L"Print Tree View of the GUI",
				[](ui::MenuTextItem& self)
				{
					self.menu().markDelete();
					_GUITree(topContainer());
				});
			return menu;
		});

	auto adc = new ui::AutoDockContainer(this, { 0, 0 }, { 100, 100 });
	adc->layoutOptions.dock = ui::Control::LayoutOptions::DockType::Fill;

	auto& fg = DataStore::root.newFrameGroup(new vg::VgFrameGroup());
	fg.name = L"newfg";

	auto da = new DrawingArea(this, fg);

	Globals::drawingToolbox->setPosition({ 50, 50 });
	Globals::currentDrawingArea->setPosition({ 150, 50 });

	/*auto tab = new ui::TabControl(this, { 100, 100 }, { 500, 400 });
	auto btn1 = new ui::Button(nullptr, {}, {}, L"Haha"),
		btn2 = new ui::Button(nullptr, {}, {}, L"Wawa");
	tab->addPage(*btn1, L"Page 1");
	tab->addPage(*btn2, L"Page 2");*/
}

bool editor::WindowManager::loadArchive(const wstring& path)
{
	assert(!path.empty());

	// ANIP_UNDONE: should first clear the current DataStore
	ifstream in(fs::ws2path(path), ios::in | ios::binary);
	try
	{
		DataStore::deserialize(in);
	}
	catch (exception& e)
	{
		ui::native::messageBox(
			r::msgErrorInOpening() + utf8s2ws(e.what()),
			ui::native::MessageType::Error);
		return false;
	}
	return true;
}

void editor::WindowManager::saveArchive(const wstring& path)
{
	assert(!path.empty());
	ofstream out(fs::ws2path(path), ios::out | ios::binary);
	DataStore::serialize(out);
	out.close();
	fileSaved = true;
}